USB CDC Control sample


Windows Runtime
usb, communications device class
Windows RT
en-US
11/25/2013

This sample shows how to communicate with a USB CDC (Communications Device Class) device and sends and receives data through serial ports, such as a USB serial converter cable. The sample demonstrates the use of the Windows.Devices.Usb namespace.

To run this sample you need:

  • USB to RS-232 serial adapters which are compatible with USB CDC standard protocol. For scenario 4-loopback, you need two adapters.
  • A serial device that can send data.
  • A null-model cable.

The sample demonstrates these key scenarios:

Windows runtime class Description
DeviceListEntry

This class stores DeviceInformation objects associated with each device, dynamically detected by the DeviceWatcher object. This class is used by the UI to display device-specific information.

DeviceList

The singleton class creates a DeviceWatcher object that finds all devices that use Winusb.sys as the device driver. The list of detected devices are shown on the UI list.

Each device in the list is a DeviceListEntry object.

CdcAcmInitialize

This class implements methods that opens the device (gets the UsbDevice object) selected by the user. After that, it instantiates the UsbSerialPort class that represents a virtual serial port.

When the user clicks the Initialize button, based on the properties selected by the user such as DTERate, ParityType, and so on, it opens the serial port for communication. All subsequent transfers are sent to or received from that port.

CdcAcmRead

The class implements methods that read from the bulk IN endpoint of the USB CDC device. The user can request a specific number of bytes to read, or can get continuous input of data read from the endpoint.

Data is read by using the DataReader object.

CdcAcmWrite

The class implements methods that write to the bulk OUT endpoint of the USB CDC device. The user can write a text string or contents of a binary file.

Data is written by using the DataWriter object.

CdcAcmLoopback

The class implements methods that opens two devices. The user writes data to an endpoint of one device and reads that data from the other device. When the page loads for this scenario, the previously selected device is removed from DeviceList.

The detected devices are added to both UI lists. When the user initializes devices, the serial port associated with the first device is opened for writing.

The serial port for the second device is opened for reading. Data is read from the first bulk IN pipe as it arrives from the first bulk OUT endpoint of the first device.

Data is read and written by using DataReader and DataWriter objects.

UsbSerialPort

This class implements a virtual COM port that exposes the underlying UsbDevice object as a serial device. It implements methods to perform these tasks:

  • Statically creates a new instance of the class. By querying the UsbDevice object, it enumerates all USB interfaces to validate that the interface class codes are either CDCControl or CDC data. It also validates that the device has bulk endpoints for data transfers.
  • Opens the serial port using the specified baud rate, parity bit, data bits, and stop bit.
  • Sends a CDC control request to a specific USB interface on the device.
  • Reads a number of bytes from the port's input buffer and writes those bytes into a byte array at the specified offset. The input buffer is mapped to the input stream of the first bulk IN pipe in the current alternate setting of the interface.
  • Writes a specified number of bytes to the serial port. Data is written to the first bulk OUT pipe in the current alternate setting of the interface.
  • Gets a value that enables the Data Terminal Ready (DTR) signal during serial communication.
  • Gets a value that indicates whether the Request to Send (RTS) signal is enabled during serial communication.
  • Gets or sets the number of milliseconds before a time-out occurs when a read operation does not finish.
  • Sends GET_LINE_CODING CDC and SET_LINE_CODING CDC requests that get and set bit rate, stop bits, parity, and number of data bits for the port.
Most operations are asynchronous (see IAsyncOperation) and the result depends on the type of operation. For example for read or write, it indicates the number of bytes read or written.

App manifest package

The sample adds the DeviceCapability element in the Package.appxmanifest file. Device information includes the device's vendor/product Ids and device class information.

To use the sample, add vendor/product id information for your USB to serial adapter to the Package.appxmanifest file. You can obtain that information from the Device Manager properties (see Hardware Id).

 <Capabilities>
    <m2:DeviceCapability Name="usb">
      <m2:Device Id="vidpid:056E 5003">
        <m2:Function Type="classId:ff * *" />
      </m2:Device>
      <m2:Device Id="vidpid:056E 5004">
        <m2:Function Type="classId:ff * *" />
      </m2:Device>
    </m2:DeviceCapability>
  </Capabilities>

Related topics

Writing a Windows store app for a USB device
Windows.Devices.Usb
Windows app samples

Related technologies

Windows.Devices.Usb

Provides Windows Runtime classes and enumerations that a Windows store app can use to communicate with an external USB device that uses WinUSB (Winusb.sys) as the device driver.

, DeviceWatcher

Enumerates devices dynamically, so that the app receives notifications if devices are added, removed, or changed after the initial enumeration is complete.

, DataReader

Reads data from an input stream. Used for reading data from a USB pipe.

, DataWriter

Writes data to an output stream. Used for writing data to a USB pipe.

Operating system requirements

Client
Windows 8.1
Server
Windows Server 2012 R2

Build the sample

Driver requirements

The sample app communicates with the device through the Microsoft-provided kernel-mode driver, Winusb.sys. You must install it as the device driver.

Hardware manufacturers can specify Winusb.sys as the device driver in either of these two ways:

  • By providing a custom INF that references the Microsoft-provided Winusb.inf file. For more information, see WinUSB (Winusb.sys) Installation.
  • By setting Microsoft operating system (OS) feature descriptors that report the compatible ID as "WINUSB". In this case, Windows matches the compatible ID with the driver and automatically loads Winusb.sys as the device driver. For more information, see WinUSB Device.
When you connect your device, you might notice that Windows loads Winusb.sys automatically. Otherwise follow these instructions to load the driver:
  1. Open Device Manager and locate the device.
  2. Right-click the device and select Update driver software... from the context menu.
  3. In the wizard, select Browse my computer for driver software.
  4. Select Let me pick from a list of device drivers on my computer.
  5. From the list of device classes, select Universal Serial Bus devices.
  6. The wizard displays WinUsb Device. Select it to load the driver.

Setting the DeviceInterfaceGUID for the device

If the device appears in Device Manager but the sample cannot detect it, make sure that the DeviceInterfaceGUID is set for this device in one of these ways:

  • If you can modify the device firmware, add the WinUSB compatible ID and DeviceInterfaceGUID in the MS OS descriptor. For more information, see Registering a device interface GUID in WinUSB Device. More information is included in this blog post: How to install WinUSB.sys without a custom INF.
  • Add the GUID in a custom INF that specifies Winusb.sys as the function driver for the device. Here is an example:

    [Dev_AddReg]

    HKR,,DeviceInterfaceGUIDs,0x10000,"{875d47fc-d331-4663-b339-624001a2dc5e}"

  • Add the GUID in the registry.
    1. Load the Wiusb.sys in Device Manager as per the instructions given in the previous section.
    2. Generate a device interface GUID by using a tool such as guidgen.exe.
    3. Find the registry key for your USB to Serial Controller device under this key. In this example, VID and PID of the device is VID_056E&PID_5004:

      HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_0564&PID_5004

    4. Under the Device Parameters key, add a String registry entry named DeviceInterfaceGUID or a Multi-String entry named DeviceInterfaceGUIDs. Set the value to the GUID you generated in step 2.
    5. Disconnect the device from the system and reconnect it to the same physical port. Apply steps 1 through 4 for each USB to Serial Controller device. Each device has a different device instance. You must add the DeviceInterfaceGUID entry for each device instance.

      Note  If you change the physical port then you must repeat steps 1 through 4.

Building the Sample

To build this sample, open the solution (.sln) file titled UsbCdc Control.sln from Microsoft Visual Studio 2013. Press F7 or go to Build->Build Solution from the top menu after the sample has loaded.

Run the sample

  1. To run this sample after building it, press F5 (run with debugging enabled) or Ctrl-F5 (run without debugging enabled), or select the corresponding options from the Debug menu. To deploy the app, select Build > Deploy UsbCdcControl.
  2. From the list of detected devices, choose your device and click the Select button.

    Note  The first time you run the sample, you will be prompted whether you allow the app to use the USB device. Choose Allow to proceed.

    If you do not see your device, most likely Winusb.sys was not loaded as the device driver.

    If you get an exception, make sure that your app manifest file contains vendor/product Ids of your USB to serial adaptor(s).

  3. Click the Initialize button. The Output string shows the device as Initialized.
  4. Choose one of the scenarios in the Select scenario input box: either 2) Read Data or 3) Write Data, and so on.
  5. To change the serial port parameters, change the values in DTERate, CharFormat, lists and click Initialize.

  6. To read data received in Bulk IN endpoint (BulkIn[0]), select 2) Read Data.

    Note  

    This scenario only reads when there is data available to read.

    This image shows continuous reading and displays data in binary format. In this case, you do not need to specify the number of bytes to read. When you want to stop reading data, click Stop Continuous Read.

    Alternatively, you can specify the number of bytes to read each time you click Read. You can also specify a timeout value. When that value is expires, the read operation completes. The default value is -1 that indicates infinite timeout.

    It blocks until completes reading the specified number of bytes are read or until the timeout value is reached.

  7. To write to the bulk OUT pipe, select 3) Write Data.

    There are two ways to write data. The simplest way is to send a text string (specified in the input box) by clicking WriteText as shown in this image. Because the Send NullTerminateChar box is checked, it adds an extra byte to the string. After the write operation is complete, the Output box shows the text and number of bytes written.

    Alternatively, you can send contents of a binary file. To do so, click Load Binary Data 1 or Load Binary Data 2and then choose a .bin file from the file picker. Then click Write Binary Data 1 or Write Binary Data 2to start the write operation.

    You can also send RS-232C break signal during a specified milliseconds time length by clicking the Send Break.

  8. To test loop back, you need two USB to RS-232 adapters which are connected with a null-modem cable. Select devices and click Initialize both devices.

    Write text in the input box and click Test Loopback. The string is displayed in the Output box.

    If To cancel the loopback test in progress, click Stop Loopback.